Coverage Report

Created: 2025-05-07 21:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
D:\a\tools.proto\tools.proto\compiler\src\compiler\structure.rs
Line
Count
Source
1
// Copyright (c) 2025, BlockProject 3D
2
//
3
// All rights reserved.
4
//
5
// Redistribution and use in source and binary forms, with or without modification,
6
// are permitted provided that the following conditions are met:
7
//
8
//     * Redistributions of source code must retain the above copyright notice,
9
//       this list of conditions and the following disclaimer.
10
//     * Redistributions in binary form must reproduce the above copyright notice,
11
//       this list of conditions and the following disclaimer in the documentation
12
//       and/or other materials provided with the distribution.
13
//     * Neither the name of BlockProject 3D nor the names of its contributors
14
//       may be used to endorse or promote products derived from this software
15
//       without specific prior written permission.
16
//
17
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29
use crate::compiler::error::Error;
30
use crate::compiler::r#enum::Enum;
31
use crate::compiler::util::objects::name_index;
32
use crate::compiler::util::try2;
33
use crate::compiler::util::types::Name;
34
use crate::compiler::Protocol;
35
use crate::model::protocol::{Description, Endianness};
36
use crate::model::structure::{SimpleType, StructFieldRaw, StructFieldView};
37
use bp3d_debug::trace;
38
use std::cell::Cell;
39
use std::fmt::{Display, Formatter};
40
use std::rc::Rc;
41
42
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
43
pub enum FixedFieldType {
44
    Int8,
45
    Int16,
46
    Int32,
47
    Int64,
48
    UInt8,
49
    UInt16,
50
    UInt32,
51
    UInt64,
52
    Float32,
53
    Float64,
54
    Bool,
55
}
56
57
impl FixedFieldType {
58
0
    pub fn get_aligned_bit_size(&self) -> usize {
59
0
        match self {
60
0
            FixedFieldType::Int8 => 8,
61
0
            FixedFieldType::Int16 => 16,
62
0
            FixedFieldType::Int32 => 32,
63
0
            FixedFieldType::Int64 => 64,
64
0
            FixedFieldType::UInt8 => 8,
65
0
            FixedFieldType::UInt16 => 16,
66
0
            FixedFieldType::UInt32 => 32,
67
0
            FixedFieldType::UInt64 => 64,
68
0
            FixedFieldType::Float32 => 32,
69
0
            FixedFieldType::Float64 => 64,
70
0
            FixedFieldType::Bool => 8
71
        }
72
0
    }
73
74
0
    pub fn is_unsigned(&self) -> bool {
75
0
        match self {
76
0
            FixedFieldType::Int8 => false,
77
0
            FixedFieldType::Int16 => false,
78
0
            FixedFieldType::Int32 => false,
79
0
            FixedFieldType::Int64 => false,
80
0
            FixedFieldType::UInt8 => true,
81
0
            FixedFieldType::UInt16 => true,
82
0
            FixedFieldType::UInt32 => true,
83
0
            FixedFieldType::UInt64 => true,
84
0
            FixedFieldType::Float32 => false,
85
0
            FixedFieldType::Float64 => false,
86
0
            FixedFieldType::Bool => false
87
        }
88
0
    }
89
90
6
    pub fn is_signed(&self) -> bool {
91
6
        match self {
92
0
            FixedFieldType::Int8 => true,
93
0
            FixedFieldType::Int16 => true,
94
0
            FixedFieldType::Int32 => true,
95
0
            FixedFieldType::Int64 => true,
96
3
            FixedFieldType::UInt8 => false,
97
0
            FixedFieldType::UInt16 => false,
98
3
            FixedFieldType::UInt32 => false,
99
0
            FixedFieldType::UInt64 => false,
100
0
            FixedFieldType::Float32 => false,
101
0
            FixedFieldType::Float64 => false,
102
0
            FixedFieldType::Bool => false,
103
        }
104
6
    }
105
}
106
107
impl Display for FixedFieldType {
108
711
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
109
711
        match self {
110
0
            FixedFieldType::Int8 => f.write_str("Int8"),
111
0
            FixedFieldType::Int16 => f.write_str("Int16"),
112
0
            FixedFieldType::Int32 => f.write_str("Int32"),
113
0
            FixedFieldType::Int64 => f.write_str("Int64"),
114
343
            FixedFieldType::UInt8 => f.write_str("UInt8"),
115
77
            FixedFieldType::UInt16 => f.write_str("UInt16"),
116
171
            FixedFieldType::UInt32 => f.write_str("UInt32"),
117
108
            FixedFieldType::UInt64 => f.write_str("UInt64"),
118
12
            FixedFieldType::Float32 => f.write_str("Float32"),
119
0
            FixedFieldType::Float64 => f.write_str("Float64"),
120
0
            FixedFieldType::Bool => f.write_str("Bool"),
121
        }
122
711
    }
123
}
124
125
682
fn map_numeric(
126
682
    ty: SimpleType,
127
682
    signed: FixedFieldType,
128
682
    unsigned: FixedFieldType,
129
682
    float: FixedFieldType,
130
682
) -> Option<FixedFieldType> {
131
682
    match ty {
132
84
        SimpleType::Signed => Some(signed),
133
586
        SimpleType::Unsigned => Some(unsigned),
134
12
        SimpleType::Float => Some(float),
135
0
        _ => None,
136
    }
137
682
}
138
139
impl FixedFieldType {
140
206
    pub fn get_byte_size(&self) -> usize {
141
206
        match self {
142
0
            FixedFieldType::Int8 => 1,
143
0
            FixedFieldType::Int16 => 2,
144
0
            FixedFieldType::Int32 => 4,
145
0
            FixedFieldType::Int64 => 8,
146
95
            FixedFieldType::UInt8 => 1,
147
24
            FixedFieldType::UInt16 => 2,
148
51
            FixedFieldType::UInt32 => 4,
149
36
            FixedFieldType::UInt64 => 8,
150
0
            FixedFieldType::Float32 => 4,
151
0
            FixedFieldType::Float64 => 8,
152
0
            FixedFieldType::Bool => 1,
153
        }
154
206
    }
155
156
18
    pub fn from_min_max_value(min_value: isize, max_value: isize) -> Result<Self, Error> {
157
18
        match min_value < 0 {
158
            true => {
159
6
                let bit_size = if max_value > i32::MAX as isize || min_value < i32::MIN as isize {
  Branch (159:35): [True: 0, False: 6]
  Branch (159:68): [True: 0, False: 6]
  Branch (159:35): [Folded - Ignored]
  Branch (159:68): [Folded - Ignored]
160
0
                    64
161
6
                } else if max_value > i16::MAX as isize || min_value < i16::MIN as isize {
  Branch (161:27): [True: 0, False: 6]
  Branch (161:60): [True: 0, False: 6]
  Branch (161:27): [Folded - Ignored]
  Branch (161:60): [Folded - Ignored]
162
0
                    32
163
6
                } else if max_value > i8::MAX as isize || min_value < i8::MIN as isize {
  Branch (163:27): [True: 0, False: 6]
  Branch (163:59): [True: 0, False: 6]
  Branch (163:27): [Folded - Ignored]
  Branch (163:59): [Folded - Ignored]
164
0
                    16
165
                } else {
166
6
                    8
167
                };
168
6
                Self::from_model(StructFieldRaw::Signed { bits: bit_size })
169
            }
170
            false => {
171
12
                let bit_size = if max_value > u32::MAX as isize {
  Branch (171:35): [True: 0, False: 12]
  Branch (171:35): [Folded - Ignored]
172
0
                    64
173
12
                } else if max_value > u16::MAX as isize {
  Branch (173:27): [True: 0, False: 12]
  Branch (173:27): [Folded - Ignored]
174
0
                    32
175
12
                } else if max_value > u8::MAX as isize {
  Branch (175:27): [True: 0, False: 12]
  Branch (175:27): [Folded - Ignored]
176
0
                    16
177
                } else {
178
12
                    8
179
                };
180
12
                Self::from_model(StructFieldRaw::Unsigned { bits: bit_size })
181
            }
182
        }
183
18
    }
184
185
88
    pub fn from_max_value(max_value: usize) -> Result<Self, Error> {
186
88
        let bit_size = if max_value > u32::MAX as usize {
  Branch (186:27): [True: 0, False: 88]
  Branch (186:27): [Folded - Ignored]
187
0
            64
188
88
        } else if max_value > u16::MAX as usize {
  Branch (188:19): [True: 12, False: 76]
  Branch (188:19): [Folded - Ignored]
189
12
            32
190
76
        } else if max_value > u8::MAX as usize {
  Branch (190:19): [True: 6, False: 70]
  Branch (190:19): [Folded - Ignored]
191
6
            16
192
        } else {
193
70
            8
194
        };
195
88
        Self::from_model(StructFieldRaw::Unsigned { bits: bit_size })
196
88
    }
197
198
749
    pub fn from_model(ty1: StructFieldRaw) -> Result<Self, Error> {
199
749
        let motherfuckingrust = ty1.clone();
200
749
        let ty = ty1.get_simple_type();
201
749
        let bit_size = ty1.get_bit_size();
202
749
        if ty == SimpleType::Boolean {
  Branch (202:12): [True: 36, False: 713]
  Branch (202:12): [Folded - Ignored]
203
36
            Ok(Self::Bool)
204
713
        } else if ty == SimpleType::Float && 
bit_size == 3242
{
  Branch (204:19): [True: 42, False: 671]
  Branch (204:46): [True: 18, False: 24]
  Branch (204:19): [Folded - Ignored]
  Branch (204:46): [Folded - Ignored]
205
18
            Ok(Self::Float32)
206
695
        } else if ty == SimpleType::Float && 
bit_size == 6424
{
  Branch (206:19): [True: 24, False: 671]
  Branch (206:46): [True: 12, False: 12]
  Branch (206:19): [Folded - Ignored]
  Branch (206:46): [Folded - Ignored]
207
12
            Ok(Self::Float64)
208
683
        } else if bit_size > 32 && 
bit_size <= 6490
{
  Branch (208:19): [True: 90, False: 593]
  Branch (208:36): [True: 90, False: 0]
  Branch (208:19): [Folded - Ignored]
  Branch (208:36): [Folded - Ignored]
209
90
            map_numeric(ty, Self::Int64, Self::UInt64, Self::Float64).ok_or(Error::UnsupportedType(motherfuckingrust))
210
593
        } else if bit_size > 16 && 
bit_size <= 32151
{
  Branch (210:19): [True: 151, False: 442]
  Branch (210:36): [True: 151, False: 0]
  Branch (210:19): [Folded - Ignored]
  Branch (210:36): [Folded - Ignored]
211
151
            map_numeric(ty, Self::Int32, Self::UInt32, Self::Float64).ok_or(Error::UnsupportedType(motherfuckingrust))
212
442
        } else if bit_size > 8 && 
bit_size <= 1672
{
  Branch (212:19): [True: 72, False: 370]
  Branch (212:35): [True: 72, False: 0]
  Branch (212:19): [Folded - Ignored]
  Branch (212:35): [Folded - Ignored]
213
72
            map_numeric(ty, Self::Int16, Self::UInt16, Self::Float32).ok_or(Error::UnsupportedType(motherfuckingrust))
214
370
        } else if bit_size > 0 && 
bit_size <= 8369
{
  Branch (214:19): [True: 369, False: 1]
  Branch (214:35): [True: 369, False: 0]
  Branch (214:19): [Folded - Ignored]
  Branch (214:35): [Folded - Ignored]
215
369
            map_numeric(ty, Self::Int8, Self::UInt8, Self::Float32).ok_or(Error::UnsupportedType(motherfuckingrust))
216
        } else {
217
1
            Err(Error::UnsupportedBitSize(bit_size))
218
        }
219
749
    }
220
}
221
222
#[derive(Clone, Debug)]
223
pub struct Location {
224
    pub byte_offset: usize,
225
    pub bit_offset: usize,
226
    pub byte_size: usize,
227
    pub bit_size: usize,
228
}
229
230
impl Display for Location {
231
708
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
232
708
        write!(
233
708
            f,
234
708
            "bytes {}..{}, bits {}..{}",
235
            self.byte_offset,
236
708
            self.byte_offset + self.byte_size,
237
            self.bit_offset,
238
708
            self.bit_offset + self.bit_size
239
        )
240
708
    }
241
}
242
243
impl Location {
244
361
    fn from_model(bit_size: usize, bit_offset: usize) -> Self {
245
361
        let byte_offset = bit_offset / 8;
246
        Self {
247
361
            byte_offset,
248
361
            bit_offset: bit_offset - byte_offset * 8,
249
361
            bit_size,
250
361
            byte_size: if bit_size % 8 != 0 {
  Branch (250:27): [True: 96, False: 265]
  Branch (250:27): [Folded - Ignored]
251
96
                (bit_size / 8) + 1
252
            } else {
253
265
                bit_size / 8
254
            },
255
        }
256
361
    }
257
}
258
259
#[derive(Clone, Debug)]
260
pub enum FieldRaw {
261
    /// Apply a raw C-like cast (used for unsigned > signed and unsigned > float of same bit size).
262
    Transmute,
263
264
    /// Apply a unsigned > signed cast on a non T-aligned value,
265
    /// the maximum positive value is passed in.
266
    SignedCast(usize),
267
268
    /// Don't do anything special, just return the raw value.
269
    None,
270
}
271
272
impl FieldRaw {
273
39
    pub fn is_none(&self) -> bool {
274
39
        
matches!0
(self, Self::None)
275
39
    }
276
277
327
    fn from_model(ty: SimpleType, bit_size: usize) -> FieldRaw {
278
327
        if ty == SimpleType::Float && 
bit_size != 3242
&&
bit_size != 6424
{
  Branch (278:12): [True: 42, False: 285]
  Branch (278:39): [True: 24, False: 18]
  Branch (278:57): [True: 12, False: 12]
  Branch (278:12): [Folded - Ignored]
  Branch (278:39): [Folded - Ignored]
  Branch (278:57): [Folded - Ignored]
279
12
            return FieldRaw::None;
280
315
        }
281
315
        if ty == SimpleType::Signed && 
bit_size != 878
&&
bit_size != 1666
&&
bit_size != 3254
&&
bit_size != 6436
{
  Branch (281:12): [True: 78, False: 237]
  Branch (281:40): [True: 66, False: 12]
  Branch (281:57): [True: 54, False: 12]
  Branch (281:75): [True: 36, False: 18]
  Branch (281:93): [True: 30, False: 6]
  Branch (281:12): [Folded - Ignored]
  Branch (281:40): [Folded - Ignored]
  Branch (281:57): [Folded - Ignored]
  Branch (281:75): [Folded - Ignored]
  Branch (281:93): [Folded - Ignored]
282
30
            let max_value = 1 << (bit_size - 1);
283
30
            FieldRaw::SignedCast(max_value - 1)
284
285
        } else if ty == SimpleType::Unsigned {
  Branch (284:19): [True: 171, False: 114]
  Branch (284:19): [Folded - Ignored]
285
171
            FieldRaw::None
286
        } else {
287
114
            FieldRaw::Transmute
288
        }
289
327
    }
290
}
291
292
#[derive(Clone, Debug)]
293
pub enum FieldView {
294
    /// Apply a float view based on an affine transformation function.
295
    Float { a: f64, b: f64, a_inv: f64, b_inv: f64 },
296
297
    /// Apply an enum view.
298
    Enum(Rc<Enum>),
299
300
    /// Don't do anything special, just return the raw value.
301
    None,
302
}
303
304
impl FieldView {
305
331
    fn from_model(
306
331
        proto: &Protocol,
307
331
        ty: SimpleType,
308
331
        bit_size: usize,
309
331
        value: Option<StructFieldView>,
310
331
    ) -> Result<Self, Error> {
311
33
        match value {
312
19
            Some(StructFieldView::Enum { name }) => {
313
19
                if ty != SimpleType::Unsigned && 
ty != SimpleType::Signed7
{
  Branch (313:20): [True: 7, False: 12]
  Branch (313:50): [True: 1, False: 6]
  Branch (313:20): [Folded - Ignored]
  Branch (313:50): [Folded - Ignored]
314
1
                    return Err(Error::UnsupportedViewType(ty));
315
18
                }
316
18
                let r = proto.enums.get(&name).ok_or(Error::UndefinedReference(name))
?0
;
317
18
                Ok(FieldView::Enum(r.clone()))
318
            }
319
7
            Some(StructFieldView::FloatRange { min, max }) => {
320
7
                if ty != SimpleType::Float {
  Branch (320:20): [True: 1, False: 6]
  Branch (320:20): [Folded - Ignored]
321
1
                    return Err(Error::UnsupportedViewType(ty));
322
6
                }
323
6
                let raw_max: usize = (1 << bit_size) - 1;
324
6
                let a = max / (raw_max as f64);
325
6
                let b = min;
326
6
                let a_inv = 1.0 / a;
327
6
                let b_inv = -b;
328
6
                Ok(FieldView::Float { a, b, a_inv, b_inv })
329
            }
330
7
            Some(StructFieldView::FloatMultiplier { multiplier }) => {
331
7
                if ty != SimpleType::Float {
  Branch (331:20): [True: 1, False: 6]
  Branch (331:20): [Folded - Ignored]
332
1
                    return Err(Error::UnsupportedViewType(ty));
333
6
                }
334
6
                let a = multiplier;
335
6
                let b = 0.0;
336
6
                let a_inv = 1.0 / a;
337
6
                let b_inv = 0.0;
338
6
                Ok(FieldView::Float { a, b, a_inv, b_inv })
339
            }
340
            None => {
341
298
                if ty == SimpleType::Float && 
bit_size != 3231
&&
bit_size != 6413
{
  Branch (341:20): [True: 31, False: 267]
  Branch (341:47): [True: 13, False: 18]
  Branch (341:65): [True: 1, False: 12]
  Branch (341:20): [Folded - Ignored]
  Branch (341:47): [Folded - Ignored]
  Branch (341:65): [Folded - Ignored]
342
1
                    return Err(Error::UnsupportedViewType(ty));
343
297
                }
344
297
                Ok(FieldView::None)
345
            }
346
        }
347
331
    }
348
}
349
350
#[derive(Clone, Debug)]
351
pub struct FixedField {
352
    pub bits_type: FixedFieldType,
353
    pub raw_type: FixedFieldType,
354
    pub view_type: FixedFieldType,
355
    pub raw: FieldRaw,
356
    pub view: FieldView,
357
    pub endianness: Endianness,
358
}
359
360
impl Display for FixedField {
361
600
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
362
600
        write!(f, "{}, {} endian", self.bits_type, self.endianness)
363
600
    }
364
}
365
366
#[derive(Clone, Debug)]
367
pub struct FixedArrayField {
368
    pub ty: FixedFieldType,
369
    pub array_len: usize,
370
    pub endianness: Endianness,
371
    pub item_bit_size: usize,
372
}
373
374
impl Display for FixedArrayField {
375
36
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
376
36
        write!(f, "{}[{}], {} endian", self.ty, self.array_len, self.endianness)
377
36
    }
378
}
379
380
#[derive(Clone, Debug)]
381
pub enum FieldType {
382
    Fixed(FixedField),
383
    Array(FixedArrayField),
384
    Struct(Rc<Structure>),
385
}
386
387
impl Display for FieldType {
388
708
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
389
708
        match self {
390
600
            FieldType::Fixed(v) => v.fmt(f),
391
36
            FieldType::Array(v) => v.fmt(f),
392
72
            FieldType::Struct(v) => f.write_str(v.name()),
393
        }
394
708
    }
395
}
396
397
impl FieldType {
398
401
    pub fn as_fixed(&self) -> Option<&FixedField> {
399
401
        match self {
400
401
            FieldType::Fixed(v) => Some(v),
401
0
            _ => None,
402
        }
403
401
    }
404
}
405
406
#[derive(Clone, Debug)]
407
pub struct Field {
408
    pub name: String,
409
    pub loc: Location,
410
    pub description: Option<Description>,
411
    pub ty: FieldType,
412
}
413
414
impl Display for Field {
415
708
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
416
708
        write!(f, "{}: {} ({})", self.name, self.ty, self.loc)
417
708
    }
418
}
419
420
impl Field {
421
369
    fn from_model(
422
369
        proto: &Protocol,
423
369
        fields: &[Field],
424
369
        mut last_bit_offset: usize,
425
369
        value: crate::model::structure::StructField,
426
369
    ) -> Result<(Self, usize), Error> {
427
369
        if (value.raw.is_none() && 
value.item_type37
.
is_none37
()) || (value.raw.is_some() &&
value.item_type332
.
is_some332
()) {
  Branch (427:13): [True: 37, False: 332]
  Branch (427:36): [True: 0, False: 37]
  Branch (427:67): [True: 332, False: 37]
  Branch (427:90): [True: 0, False: 332]
  Branch (427:13): [Folded - Ignored]
  Branch (427:36): [Folded - Ignored]
  Branch (427:67): [Folded - Ignored]
  Branch (427:90): [Folded - Ignored]
428
0
            return Err(Error::BadFieldType);
429
369
        }
430
369
        let (
ty361
,
bit_size361
) = if let Some(
info332
) = value.raw {
  Branch (430:37): [True: 332, False: 37]
  Branch (430:37): [Folded - Ignored]
431
332
            let array_len = value.array_len.unwrap_or(1);
432
332
            if array_len == 0 {
  Branch (432:16): [True: 1, False: 331]
  Branch (432:16): [Folded - Ignored]
433
1
                return Err(Error::ZeroArray);
434
331
            }
435
331
            let mut bit_size = info.get_bit_size();
436
331
            let 
view327
= FieldView::from_model(proto, info.get_simple_type(), bit_size, value.view)
?4
;
437
327
            let raw = FieldRaw::from_model(info.get_simple_type(), bit_size);
438
327
            bit_size *= array_len;
439
327
            let 
ty326
= FixedFieldType::from_model(info)
?1
;
440
326
            if array_len > 1 {
  Branch (440:16): [True: 19, False: 307]
  Branch (440:16): [Folded - Ignored]
441
19
                if (bit_size / array_len) % 8 != 0 {
  Branch (441:20): [True: 1, False: 18]
  Branch (441:20): [Folded - Ignored]
442
1
                    return Err(Error::UnalignedArrayCodec);
443
18
                }
444
18
                (
445
18
                    FieldType::Array(FixedArrayField {
446
18
                        endianness: proto.endianness,
447
18
                        array_len,
448
18
                        ty,
449
18
                        item_bit_size: bit_size / array_len,
450
18
                    }),
451
18
                    bit_size,
452
18
                )
453
            } else {
454
307
                let bits_type = FixedFieldType::from_model(StructFieldRaw::Unsigned { bits: bit_size })
?0
;
455
307
                let raw_type = match (bit_size, ty) {
456
12
                    (32, FixedFieldType::Float32) => FixedFieldType::Float32,
457
12
                    (64, FixedFieldType::Float64) => FixedFieldType::Float64,
458
6
                    (_, FixedFieldType::Float32) => bits_type,
459
6
                    (_, FixedFieldType::Float64) => bits_type,
460
271
                    _ => ty,
461
                };
462
307
                (
463
307
                    FieldType::Fixed(FixedField {
464
307
                        endianness: proto.endianness,
465
307
                        bits_type,
466
307
                        raw_type,
467
307
                        view_type: ty,
468
307
                        view,
469
307
                        raw,
470
307
                    }),
471
307
                    bit_size,
472
307
                )
473
            }
474
        } else {
475
37
            let item_type = unsafe { value.item_type.unwrap_unchecked() };
476
37
            let 
r36
=
try2!36
(proto.structs.get(&item_type) =>
Error::UndefinedReference(item_type)1
);
477
36
            trace!("Solved reference {} => {:?}", item_type, r);
478
36
            (FieldType::Struct(r.clone()), r.bit_size)
479
        };
480
361
        let loc = match value.offset {
481
            None => {
482
349
                let loc = Location::from_model(bit_size, last_bit_offset);
483
349
                last_bit_offset += bit_size;
484
349
                loc
485
            }
486
12
            Some(v) => match v.relative_to {
487
                None => {
488
6
                    let start_bits = v.bits.unwrap_or(0);
489
6
                    let end_bits = start_bits + bit_size;
490
6
                    if end_bits > last_bit_offset {
  Branch (490:24): [True: 0, False: 6]
  Branch (490:24): [Folded - Ignored]
491
0
                        last_bit_offset = end_bits;
492
6
                    }
493
6
                    Location::from_model(bit_size, start_bits)
494
                }
495
6
                Some(name) => {
496
36
                    let 
field6
=
fields.iter()6
.
find6
(|v| v.name == name).
ok_or6
(
Error::UndefinedReference(name)6
)
?0
;
497
6
                    let start_bits = field.loc.bit_offset + v.bits.unwrap_or(0);
498
6
                    let end_bits = start_bits + bit_size;
499
6
                    if end_bits > last_bit_offset {
  Branch (499:24): [True: 0, False: 6]
  Branch (499:24): [Folded - Ignored]
500
0
                        last_bit_offset = end_bits;
501
6
                    }
502
6
                    Location::from_model(bit_size, start_bits)
503
                }
504
            },
505
        };
506
361
        Ok((
507
361
            Self {
508
361
                name: value.name,
509
361
                ty,
510
361
                loc,
511
361
                description: value.description,
512
361
            },
513
361
            last_bit_offset,
514
361
        ))
515
369
    }
516
}
517
518
#[derive(Clone, Debug)]
519
pub struct Structure {
520
    pub name: String,
521
    pub description: Option<Description>,
522
    pub fields: Vec<Field>,
523
    pub byte_size: usize,
524
    pub bit_size: usize,
525
    used_in_header: Cell<bool>,
526
}
527
528
impl Structure {
529
26
    pub fn set_used_in_header(&self) {
530
26
        self.used_in_header.set(true);
531
26
    }
532
533
120
    pub fn is_used_in_header(&self) -> bool {
534
120
        self.used_in_header.get()
535
120
    }
536
537
196
    pub fn from_model(proto: &Protocol, value: crate::model::structure::Structure) -> Result<Structure, Error> {
538
196
        let mut fields = Vec::with_capacity(value.fields.len());
539
196
        let mut last_bit_offset = 0;
540
557
        for 
field369
in value.fields {
541
369
            let (
field361
,
new_offset361
) = Field::from_model(proto, &fields, last_bit_offset, field)
?8
;
542
361
            fields.push(field);
543
361
            last_bit_offset = new_offset;
544
        }
545
188
        let s = Structure {
546
188
            name: value.name,
547
188
            description: value.description,
548
188
            fields,
549
188
            bit_size: last_bit_offset,
550
188
            byte_size: if last_bit_offset % 8 != 0 {
  Branch (550:27): [True: 0, False: 188]
  Branch (550:27): [Folded - Ignored]
551
0
                (last_bit_offset / 8) + 1
552
            } else {
553
188
                last_bit_offset / 8
554
            },
555
188
            used_in_header: Cell::new(false),
556
        };
557
188
        if s.bit_size == 0 {
  Branch (557:12): [True: 1, False: 187]
  Branch (557:12): [Folded - Ignored]
558
1
            return Err(Error::ZeroStruct);
559
187
        }
560
187
        Ok(s)
561
196
    }
562
}
563
564
name_index!(Structure => name);